package com.waterdispenser.socket;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.waterdispenser.entity.TMachine;
import com.waterdispenser.entity.TStudent;
import com.waterdispenser.service.impl.TMachineServiceImpl;
import com.waterdispenser.service.impl.TStudentServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.time.LocalDateTime;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @author: yiranxiaohui
 * @project: SocketServer
 * @createTime: 2023/3/7 10:52
 */
@Controller
public class StartSocket extends Thread{
    @Autowired
    TMachineServiceImpl tMachineService;
    @Autowired
    TStudentServiceImpl tStudentService;

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    //使用多线程，需要线程池，防止并发过高时创建过多线程耗尽资源
    private final ExecutorService threadPool = Executors.newCachedThreadPool();
    public ServerSocket serverSocket;
    @Autowired
    public SocketArray socketArray;
    Integer port = 8234;

    @Override
    public void run() {
        super.run();
        while(true) {
            // 接收连接，如果没有连接，accept() 方法会阻塞
            try {
                Socket socket = serverSocket.accept();
                String machineIp = socket.getInetAddress().getHostAddress();
                if(socketArray.getSocketHashMap().containsKey(machineIp)) socketArray.getSocketHashMap().replace(machineIp, socket);
                else socketArray.getSocketHashMap().put(machineIp, socket);
                System.out.println(machineIp);
                Runnable runnable = () -> {
                    // 获取输入流，并使用 BufferedInputStream 和 InputStreamReader 装饰，方便以字符流的形式处理，方便一行行读取内容
                    try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
                        String msg;
                        char[] cbuf = new char[1024];
                        int len;
                        while ((len = in.read(cbuf, 0, 1024)) != -1) {
                            // 循环读取输入流中的内容
                            msg = new String(cbuf, 0, len);
                            System.out.println(msg);
                            if ("stop!".equals(msg)) {
                                in.read();
                                break;
                            }
                            TMachine tMachine = tMachineService.getOne(new QueryWrapper<TMachine>().eq("local_ip", machineIp));
                            if("#".equals(String.valueOf(msg.charAt(0)))){
                                int index = msg.indexOf(' ');
                                String cardNumber = msg.substring(1,index);
                                String waterIntake = msg.substring(index + 1);
                                System.out.println("tMachine = " + tMachine.getId());
                                System.out.println("cardNumber = " + cardNumber + "、waterIntake = " + waterIntake);
                                // 保存学生饮水信息
                                boolean save = tStudentService.save(new TStudent(null, Long.parseLong(cardNumber), tMachine.getId(), LocalDateTime.now(), Integer.parseInt(waterIntake)));
                                System.out.println("save = " + save);
                            } else if("$".equals(String.valueOf(msg.charAt(0)))){
                                tMachine.setDrinkingWaterQuality(Integer.valueOf(msg.substring(1)));
                                tMachine.setSourceWaterQuality(Integer.valueOf(msg.substring(1)));
                                tMachineService.updateById(tMachine);
                            } else if("Error1".equals(msg)){
                                tMachine.setState(-1);
                                tMachineService.updateById(tMachine);
                            } else if("%".equals(msg)){
                                tMachine.setState(0);
                                tMachineService.updateById(tMachine);
                            } else if("Warning1".equals(msg.substring(0,msg.indexOf('$')))){
                                tMachine.setState(-2);
                                int i = msg.indexOf('$');
                                System.out.println(Integer.valueOf(msg.substring(i+1)));
                                tMachine.setDrinkingWaterQuality(Integer.valueOf(msg.substring(i+1)));
                                tMachine.setSourceWaterQuality(Integer.valueOf(msg.substring(i+1)));
                                tMachineService.updateById(tMachine);
                            }
                        }
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                };
                //接收线程返回结果
                Future future = threadPool.submit(runnable);
                logger.info("{}", future);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public StartSocket(){
        try {
            serverSocket = new ServerSocket(port);
            logger.info("Socket服务已启动，占用端口： {}", serverSocket.getLocalPort());
            start();
        }catch (IOException e){
            logger.error("端口异常信息",e);
            System.exit(0);
        }
    }
}
